using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Logging;
using Volo.Abp.DependencyInjection;

namespace MatrixFramework.Shared.Application.CodeQuality
{
    /// <summary>
    /// 代码分析器 - 用于检查代码质量
    /// </summary>
    public class CodeAnalyzer : ITransientDependency
    {
        private readonly ILogger<CodeAnalyzer> _logger;

        public CodeAnalyzer(ILogger<CodeAnalyzer> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 分析C#代码文件
        /// </summary>
        public CodeAnalysisResult AnalyzeCSharpFile(string filePath)
        {
            if (!File.Exists(filePath))
            {
                throw new FileNotFoundException($"文件不存在: {filePath}");
            }

            var content = File.ReadAllText(filePath);
            var result = new CodeAnalysisResult
            {
                FilePath = filePath,
                FileName = Path.GetFileName(filePath),
                AnalysisTime = DateTime.UtcNow
            };

            try
            {
                // 基础代码分析
                AnalyzeBasicMetrics(content, result);

                // 命名规范检查
                AnalyzeNamingConventions(content, result);

                // 方法复杂度分析
                AnalyzeMethodComplexity(content, result);

                // 异步编程检查
                AnalyzeAsyncPatterns(content, result);

                // 安全性检查
                AnalyzeSecurityIssues(content, result);

                // 性能问题检查
                AnalyzePerformanceIssues(content, result);

                // 文档完整性检查
                AnalyzeDocumentation(content, result);

                // 计算总体评分
                result.OverallScore = CalculateOverallScore(result);

                _logger.LogInformation("代码分析完成: {File}, 评分: {Score}", filePath, result.OverallScore);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "分析文件 {File} 时发生错误", filePath);
                result.Errors.Add($"分析失败: {ex.Message}");
            }

            return result;
        }

        /// <summary>
        /// 分析项目中的所有C#文件
        /// </summary>
        public ProjectAnalysisResult AnalyzeProject(string projectPath)
        {
            var result = new ProjectAnalysisResult
            {
                ProjectPath = projectPath,
                AnalysisTime = DateTime.UtcNow
            };

            var csFiles = Directory.GetFiles(projectPath, "*.cs", SearchOption.AllDirectories);

            _logger.LogInformation("开始分析项目 {Project}, 文件数量: {Count}", projectPath, csFiles.Length);

            foreach (var file in csFiles)
            {
                try
                {
                    var fileResult = AnalyzeCSharpFile(file);
                    result.FileResults.Add(fileResult);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "分析文件 {File} 失败", file);
                    result.FailedFiles.Add(file);
                }
            }

            // 计算项目总体统计
            CalculateProjectStatistics(result);

            _logger.LogInformation("项目分析完成，总体评分: {Score}", result.OverallScore);
            return result;
        }

        private void AnalyzeBasicMetrics(string content, CodeAnalysisResult result)
        {
            var lines = content.Split('\n');
            result.TotalLines = lines.Length;
            result.CodeLines = lines.Count(line => !string.IsNullOrWhiteSpace(line) && !line.Trim().StartsWith("//"));
            result.CommentLines = lines.Count(line => line.Trim().StartsWith("//"));
            result.EmptyLines = lines.Count(string.IsNullOrWhiteSpace);

            // 计算类数量
            result.ClassCount = Regex.Matches(content, @"\bclass\s+\w+").Count;

            // 计算方法数量
            result.MethodCount = Regex.Matches(content, @"\b(public|private|protected|internal)\s+(?:static\s+)?(?:async\s+)?\w+\s*\(.*?\)\s*(?:{|=>)").Count;

            // 计算接口数量
            result.InterfaceCount = Regex.Matches(content, @"\binterface\s+\w+").Count;
        }

        private void AnalyzeNamingConventions(string content, CodeAnalysisResult result)
        {
            // 检查类命名（PascalCase）
            var classMatches = Regex.Matches(content, @"\bclass\s+([a-zA-Z][a-zA-Z0-9_]*)");
            foreach (Match match in classMatches)
            {
                var className = match.Groups[1].Value;
                if (!IsPascalCase(className) && !className.EndsWith("Tests"))
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.NamingConvention,
                        Severity = Severity.Warning,
                        Message = $"类名 '{className}' 应使用PascalCase命名规范",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }

            // 检查方法命名（PascalCase）
            var methodMatches = Regex.Matches(content, @"\b(public|private|protected|internal)\s+(?:static\s+)?(?:async\s+)?([a-zA-Z][a-zA-Z0-9_]*)\s*\(.*?\)");
            foreach (Match match in methodMatches)
            {
                var methodName = match.Groups[2].Value;
                if (!IsPascalCase(methodName))
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.NamingConvention,
                        Severity = Severity.Warning,
                        Message = $"方法名 '{methodName}' 应使用PascalCase命名规范",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }

            // 检查变量命名（camelCase）
            var variableMatches = Regex.Matches(content, @"(?:var|private|readonly)\s+([a-z][a-zA-Z0-9_]*)\s*[=;]");
            foreach (Match match in variableMatches)
            {
                var variableName = match.Groups[1].Value;
                if (!IsCamelCase(variableName))
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.NamingConvention,
                        Severity = Severity.Info,
                        Message = $"变量名 '{variableName}' 应使用camelCase命名规范",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }
        }

        private void AnalyzeMethodComplexity(string content, CodeAnalysisResult result)
        {
            var methodBlocks = Regex.Matches(content, @"(?:public|private|protected|internal)\s+(?:static\s+)?(?:async\s+)?\w+\s*\(.*?\)\s*\{(.*?)\n\s*\}", RegexOptions.Singleline);

            foreach (Match match in methodBlocks)
            {
                var methodContent = match.Groups[1].Value;
                var lineCount = methodContent.Split('\n').Length;

                if (lineCount > 100)
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.Complexity,
                        Severity = Severity.Error,
                        Message = $"方法过长 ({lineCount} 行)，建议拆分为更小的方法",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
                else if (lineCount > 50)
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.Complexity,
                        Severity = Severity.Warning,
                        Message = $"方法较长 ({lineCount} 行)，考虑是否可以简化",
                        Line = GetLineNumber(content, match.Index)
                    });
                }

                // 检查嵌套深度
                var maxDepth = CalculateNestingDepth(methodContent);
                if (maxDepth > 4)
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.Complexity,
                        Severity = Severity.Warning,
                        Message = $"方法嵌套过深 (最大深度: {maxDepth})，建议简化逻辑",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }
        }

        private void AnalyzeAsyncPatterns(string content, CodeAnalysisResult result)
        {
            // 检查async void的使用
            var asyncVoidMatches = Regex.Matches(content, @"\basync\s+void\s+\w+\s*\(.*?\)");
            foreach (Match match in asyncVoidMatches)
            {
                // 排除事件处理器
                if (!content.Substring(0, match.Index).Contains("EventHandler"))
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.AsyncPattern,
                        Severity = Severity.Error,
                        Message = "避免使用async void，应使用async Task",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }

            // 检查.Result的使用（可能阻塞）
            var resultMatches = Regex.Matches(content, @"\.Result\s*[;)");
            foreach (Match match in resultMatches)
            {
                result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.AsyncPattern,
                        Severity = Severity.Warning,
                        Message = "避免使用.Result，可能导致死锁",
                        Line = GetLineNumber(content, match.Index)
                    });
            }

            // 检查.Wait()的使用（可能阻塞）
            var waitMatches = Regex.Matches(content, @"\.Wait\(\)");
            foreach (Match match in waitMatches)
            {
                result.Issues.Add(new CodeIssue
                {
                    Type = IssueType.AsyncPattern,
                    Severity = Severity.Warning,
                    Message = "避免使用.Wait()，可能导致死锁",
                    Line = GetLineNumber(content, match.Index)
                });
            }
        }

        private void AnalyzeSecurityIssues(string content, CodeAnalysisResult result)
        {
            // 检查SQL注入风险
            var sqlInjectionPatterns = new[]
            {
                @"string\.sql\s*=\s*"".*""\s*\+",
                @"string\.sql\s*\+=\s*"".*""",
                @"ExecuteNonQuery\("".*\+.*""",
                @"ExecuteQuery\("".*\+.*"""
            };

            foreach (var pattern in sqlInjectionPatterns)
            {
                var matches = Regex.Matches(content, pattern);
                foreach (Match match in matches)
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.Security,
                        Severity = Severity.Error,
                        Message = "可能存在SQL注入风险，请使用参数化查询",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }

            // 检查硬编码的密码或密钥
            var hardcodedSecrets = Regex.Matches(content, @"(?:password|secret|key)\s*=\s*""[^""]{4,}""");
            foreach (Match match in hardcodedSecrets)
            {
                result.Issues.Add(new CodeIssue
                {
                    Type = IssueType.Security,
                    Severity = Severity.Error,
                    Message = "检测到硬编码的密码或密钥，存在安全风险",
                    Line = GetLineNumber(content, match.Index)
                });
            }

            // 检查异常信息泄露
            var exceptionExposure = Regex.Matches(content, @"catch\s*\([^)]*Exception[^)]*\)\s*\{[^}]*Console\.(Write|WriteLine)");
            foreach (Match match in exceptionExposure)
            {
                result.Issues.Add(new CodeIssue
                {
                    Type = IssueType.Security,
                    Severity = Severity.Warning,
                    Message = "异常信息可能泄露敏感数据，建议使用日志记录",
                    Line = GetLineNumber(content, match.Index)
                });
            }
        }

        private void AnalyzePerformanceIssues(string content, CodeAnalysisResult result)
        {
            // 检查字符串拼接
            var stringConcatenation = Regex.Matches(content, @"""[^""]*\s*\+\s*""");
            foreach (Match match in stringConcatenation)
            {
                result.Issues.Add(new CodeIssue
                {
                    Type = IssueType.Performance,
                    Severity = Severity.Info,
                    Message = "建议使用StringBuilder或字符串插值代替字符串拼接",
                    Line = GetLineNumber(content, match.Index)
                });
            }

            // 检查可能的内存泄漏
            var idisposableNotDisposed = Regex.Matches(content, @"new\s+(FileStream|StreamReader|StreamWriter|HttpClient)[^}]*\{[^}]*}", RegexOptions.Singleline);
            foreach (Match match in idisposableNotDisposed)
            {
                if (!match.Value.Contains("using"))
                {
                    result.Issues.Add(new CodeIssue
                    {
                        Type = IssueType.Performance,
                        Severity = Severity.Warning,
                        Message = "IDisposable对象未正确释放，建议使用using语句",
                        Line = GetLineNumber(content, match.Index)
                    });
                }
            }

            // 检查LINQ的性能问题
            var linqIssues = Regex.Matches(content, @"\.Where\(.*\)\.Count\(\)");
            foreach (Match match in linqIssues)
            {
                result.Issues.Add(new CodeIssue
                {
                    Type = IssueType.Performance,
                    Severity = Severity.Info,
                    Message = "建议使用.Any()代替.Where().Count()来提高性能",
                    Line = GetLineNumber(content, match.Index)
                });
            }
        }

        private void AnalyzeDocumentation(string content, CodeAnalysisResult result)
        {
            // 检查公共方法是否有XML文档注释
            var publicMethods = Regex.Matches(content, @"///\s*<summary>.*?</summary>.*?public\s+(?:static\s+)?(?:async\s+)?\w+\s*\(", RegexOptions.Singleline);
            var allPublicMethods = Regex.Matches(content, @"public\s+(?:static\s+)?(?:async\s+)?\w+\s*\(");

            result.DocumentedMethods = publicMethods.Count;
            result.UndocumentedMethods = allPublicMethods.Count - publicMethods.Count;

            if (result.UndocumentedMethods > 0)
            {
                result.Issues.Add(new CodeIssue
                {
                    Type = IssueType.Documentation,
                    Severity = Severity.Info,
                    Message = $"发现 {result.UndocumentedMethods} 个公共方法缺少XML文档注释"
                });
            }
        }

        private int CalculateOverallScore(CodeAnalysisResult result)
        {
            var score = 100.0;

            // 根据问题严重程度扣分
            foreach (var issue in result.Issues)
            {
                switch (issue.Severity)
                {
                    case Severity.Error:
                        score -= 5;
                        break;
                    case Severity.Warning:
                        score -= 2;
                        break;
                    case Severity.Info:
                        score -= 1;
                        break;
                }
            }

            // 根据方法长度扣分
            if (result.MethodCount > 0)
            {
                var avgLinesPerMethod = (double)result.CodeLines / result.MethodCount;
                if (avgLinesPerMethod > 30)
                    score -= 5;
                else if (avgLinesPerMethod > 20)
                    score -= 2;
            }

            // 根据文档完整性调整分数
            if (result.MethodCount > 0)
            {
                var documentationRatio = (double)result.DocumentedMethods / result.MethodCount;
                score += (documentationRatio - 0.8) * 10; // 80%以上加分，以下扣分
            }

            return Math.Max(0, Math.Min(100, (int)Math.Round(score, 1)));
        }

        private void CalculateProjectStatistics(ProjectAnalysisResult result)
        {
            if (!result.FileResults.Any()) return;

            result.OverallScore = result.FileResults.Average(r => r.OverallScore);
            result.TotalFiles = result.FileResults.Count;
            result.TotalIssues = result.FileResults.Sum(r => r.Issues.Count);
            result.TotalErrors = result.FileResults.Sum(r => r.Issues.Count(i => i.Severity == Severity.Error));
            result.TotalWarnings = result.FileResults.Sum(r => r.Issues.Count(i => i.Severity == Severity.Warning));

            // 按问题类型统计
            result.IssueBreakdown = result.FileResults
                .SelectMany(r => r.Issues)
                .GroupBy(i => i.Type)
                .ToDictionary(g => g.Key, g => g.Count());
        }

        private bool IsPascalCase(string name)
        {
            return !string.IsNullOrEmpty(name) && char.IsUpper(name[0]) && !name.Contains("_");
        }

        private bool IsCamelCase(string name)
        {
            return !string.IsNullOrEmpty(name) && char.IsLower(name[0]) && !name.Contains("_");
        }

        private int GetLineNumber(string content, int index)
        {
            return content.Substring(0, index).Count(c => c == '\n') + 1;
        }

        private int CalculateNestingDepth(string content)
        {
            var maxDepth = 0;
            var currentDepth = 0;

            foreach (var line in content.Split('\n'))
            {
                var trimmedLine = line.Trim();
                if (trimmedLine.StartsWith("{"))
                    currentDepth++;
                else if (trimmedLine.StartsWith("}"))
                    currentDepth--;

                if (currentDepth > maxDepth)
                    maxDepth = currentDepth;
            }

            return maxDepth;
        }
    }

    #region 数据模型

    public class CodeAnalysisResult
    {
        public string FilePath { get; set; } = string.Empty;
        public string FileName { get; set; } = string.Empty;
        public DateTime AnalysisTime { get; set; }

        // 基础指标
        public int TotalLines { get; set; }
        public int CodeLines { get; set; }
        public int CommentLines { get; set; }
        public int EmptyLines { get; set; }
        public int ClassCount { get; set; }
        public int MethodCount { get; set; }
        public int InterfaceCount { get; set; }

        // 文档指标
        public int DocumentedMethods { get; set; }
        public int UndocumentedMethods { get; set; }

        // 问题列表
        public List<CodeIssue> Issues { get; set; } = new();
        public List<string> Errors { get; set; } = new();

        // 评分
        public double OverallScore { get; set; }
    }

    public class ProjectAnalysisResult
    {
        public string ProjectPath { get; set; } = string.Empty;
        public DateTime AnalysisTime { get; set; }

        public List<CodeAnalysisResult> FileResults { get; set; } = new();
        public List<string> FailedFiles { get; set; } = new();

        // 项目统计
        public int TotalFiles { get; set; }
        public double OverallScore { get; set; }
        public int TotalIssues { get; set; }
        public int TotalErrors { get; set; }
        public int TotalWarnings { get; set; }

        public Dictionary<IssueType, int> IssueBreakdown { get; set; } = new();
    }

    public class CodeIssue
    {
        public IssueType Type { get; set; }
        public Severity Severity { get; set; }
        public string Message { get; set; } = string.Empty;
        public int Line { get; set; }
    }

    public enum IssueType
    {
        NamingConvention,
        Complexity,
        AsyncPattern,
        Security,
        Performance,
        Documentation
    }

    public enum Severity
    {
        Info,
        Warning,
        Error
    }

    #endregion
}